\documentclass[a4paper,12pt]{article}

\usepackage[margin=1.5cm]{geometry}
\usepackage{listings}
\usepackage{enumitem}

\title{Some Interesting Things in C}
\author{Chen Rushan\\chenrsster@gmail.com}
\date{2009.10.24 15:10}

\setlength{\parskip}{1.2ex}
\setlength{\parindent}{0pt}

\lstset{
    frame=single, framesep=0pt, framexleftmargin=-1pt, framextopmargin=3pt,
    framexbottommargin=3pt, aboveskip=0.5cm, belowskip=0.2cm, columns=flexible,
    basicstyle=\ttfamily
}

\begin{document}

\maketitle

\section{Access local variables from other function}

    We are all told that a function can only access the local variables within
    it, and there's no way that we can access other function's, but nothing is 
    impossible.

    With the knowledge about how the procedure activation record looks like,
    and how C arranges the stack when calling functions, we can write a
    function which access other function's local variables:

    \begin{lstlisting}[gobble=3]
    int
    main(int argc, char **argv)
    {
            func1(1, 2);

            return 0;
    }

    void
    func1(int i1, int i2)
    {
            int i = 1;
            int j = 23;

            func2(i);
    }

    void
    func2(int i)
    {
            printf("%d %d\n", *(\&i + 6), *(\&i + 7));
    }
    \end{lstlisting}

    I omitted some trivial parts of this program, the output of it is:

    \begin{lstlisting}[gobble=3]
    1 23
    \end{lstlisting}

    The reason can easily be uncovered by inspecting its corresponding assembly
    code. In my case, {\em func1} allocates 40 bytes after {\em \%ebp} for
    temporary use, and {\em i} resides in {\em -16(\%ebp)}, {\em j} in{\em
    -12(\%ebp)}. When calling {\em func2}, the argument is put in {\em
    (\%ebp)}, so to access {\em i, j}, we need to add some offset, as \&i + 6,
    \&j + 7.

    Note that there're two points you need to pay special attention:

    \begin{enumerate}[topsep=0pt]
        \item It's \&i \textbf{+} 6, \textbf{NOT} \&i - 6.
        \item It's \&i + \textbf{6}, \textbf{NOT} \&i + 24, since {\em i} is an
            int, so \&i points to an int, when plus 6, 24 bytes are actually 
            added in.
    \end{enumerate}

\end{document}

